.DEFAULT_GOAL = all
WORK_DIR  := $(shell pwd)
OBJ_DIR   := $(WORK_DIR)/build
BIN_DIR   := $(WORK_DIR)/bin
LIB_DIR   := $(WORK_DIR)/lib
BUILD_DIR := $(WORK_DIR)/build
DEPS      := $(foreach dep,$(DEPS),$(realpath $(dep)))
INC_PATH  := $(WORK_DIR) $(DEPS) $(HOME) $(INC_PATH)
## we only use basics module's file with header
## if the file is changed, we should rebuild almost everything
INC_FILE  := $(wildcard $(HOME)/basics/*.h)
INCLUDES  := $(addprefix -I, $(INC_PATH))
# build flags
## about -MMD: export the dependencies of a .c file into .d
## it can be reused as dependencies of $(NAME)
CFLAGS    := -MMD -g -Og -fPIC -Wall -Werror $(INCLUDES) $(CFLAGS)
LDFLAGS   := -g -Og $(LDFLAGS)

OBJS      := $(SRCS:%.c=$(OBJ_DIR)/%.o)

## '-' ignores errors when the required '*.d' file
## is not available
-include $(OBJS:.o=.d)

$(OBJ_DIR)/%.o: %.c $(INC_FILE)
	@echo - Compiling $<
	@mkdir -p $(dir $@)
	@$(CC) $(CFLAGS) -c -o $@ $<

## libs should be detected after dependency modules being built
DEP-LIBS   = $(foreach dep,$(DEPS),$(wildcard $(dep)/lib/*))
DEP-SRCS  := $(foreach dep,$(DEPS),$(wildcard $(dep)/*.c) $(wildcard $(dep)/*.h))

LIBS      += -lc
LIBS      += $(DEP-LIBS)
## this is equivalent to --dynamic-linker=/lib/ld-linux-x86-64.so.2
LINKER    := -I$(realpath $(shell gcc --print-file-name=ld-linux-x86-64.so.2))

## If the object is a .so file
ifeq ($(filter %.so,$(NAME)), $(NAME))
	DYNAMIC_LIB = $(LIB_DIR)/$(NAME)
	LDFLAGS    += -shared
## If the object is a .a file
else ifeq ($(filter %.a,$(NAME)), $(NAME))
	STATIC_LIB  = $(LIB_DIR)/$(NAME)
	ARFLAGS	   := cr
## If the object is an executable file
else
	BINARY      = $(BIN_DIR)/$(NAME)
	RUNTIME    := $(realpath $(shell gcc --print-file-name=crt1.o))
	# INC_LIBS += -L $(realpath $(LIB_DIR))
endif

$(DEPS):
	@$(MAKE) -s -C $@

## Really hacky, I don't want to do this, but this seems to be the only way
$(DYNAMIC_LIB): $(OBJS) $(DEP-SRCS)
	@echo - Linking files into dynamic library $@
	@mkdir -p $(dir $@)
	@$(LD) -o $@ $(LDFLAGS) $(LINKER) $(OBJS) $(INC_LIBS) $(LIBS)

$(STATIC_LIB): $(OBJS) $(DEP-SRCS)
	@echo - Linking files into static library $@
	@mkdir -p $(dir $@)
	@$(AR) $(ARFLAGS) $@ $(OBJS) $(LIBS)

$(BINARY): $(OBJS) $(DEP-SRCS)
	@echo - Linking files into executable $@
	@mkdir -p $(dir $@)
	@$(LD) -o $@ $(LDFLAGS) $(LINKER) $(RUNTIME) $(OBJS) $(INC_LIBS) $(LIBS)

all: $(DEPS) $(DYNAMIC_LIB) $(STATIC_LIB) $(BINARY)
## '-' ignores errors while running rm
clean:
	@for i in $(DEPS); do $(MAKE) clean -s -C $$i; done
	@-rm -rf $(BUILD_DIR)
	@-rm -rf $(BIN_DIR)
	@-rm -rf $(LIB_DIR)

# run:
# 	@for app in $(wildcard bin/*); do $$app; done

.PHONY: all clean run $(DEPS)
